﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIMCObjetoNegocio;

namespace SIMCRepositorio
{

    public interface IRepositorioFiltro
    {
        FiltroPortafolio Buscar(int p_IdFiltro);
        List<FiltroPortafolio> Buscar();
        FiltroPortafolio BuscarPorPerfil(string p_IdPerfil);
        List<Rol> BuscarPerfilesAsociados(int p_IdFiltro);
        List<Rol> BuscarPerfilesSinFiltro();
        int Crear(FiltroPortafolio p_Filtro);
        void Eliminar(int p_IdFiltro);
        void Actualizar(FiltroPortafolio p_Filtro);
        void AsociarPerfiles(int p_IdFiltro, List<string> p_Perfiles);       
        void EliminarAsociaciones(int p_IdFiltro, List<string> p_Perfiles);
    }

    public class RepositorioFiltro : Database, IRepositorioFiltro
    {
        public FiltroPortafolio Buscar(int p_IdFiltro)
        {
            try
            {

                var query = from filtro in Context.adm_filtro
                            where filtro.flp_iCodigo == p_IdFiltro
                            select new FiltroPortafolio
                            {
                                Id = filtro.flp_iCodigo,
                                Descripcion = filtro.flp_sDescripcion,
                                Query = filtro.flp_sQuery
                            };

                return query.SingleOrDefault();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
        public List<FiltroPortafolio> Buscar()
        {
            try
            {
                var query = from filtro in Context.adm_filtro
                            select new FiltroPortafolio
                            {
                                Id = filtro.flp_iCodigo,
                                Descripcion= filtro.flp_sDescripcion,
                                Query = filtro.flp_sQuery                                 
                            };

                return query.ToList();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public FiltroPortafolio BuscarPorPerfil(string p_IdPerfil)
        {
            try
            {
                var query = from filtro in Context.adm_filtro
                            join Perfiles in Context.adm_filtro_perfil
                                on filtro.flp_iCodigo equals Perfiles.flg_iCodigoFiltro 
                            where Perfiles.flg_sCodigoGrupoUsuario == p_IdPerfil
                            select new FiltroPortafolio
                            {
                                Id = filtro.flp_iCodigo,
                                Descripcion = filtro.flp_sDescripcion,
                                Query = filtro.flp_sQuery
                            };

                return query.SingleOrDefault();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<Rol> BuscarPerfilesAsociados(int p_IdFiltro)
        {
            try
            {
                IRepositorioUsuario repUsuario = DatabaseAccess.UsuarioRepositorio;

                List<Rol> roles = repUsuario.BuscarRoles();

                var query = from r in roles
                            join perf in Context.adm_filtro_perfil on r.Id equals perf.flg_sCodigoGrupoUsuario
                            where perf.flg_iCodigoFiltro == p_IdFiltro
                            select new SIMCObjetoNegocio.Rol
                            {
                                Id = r.Id,
                                Descripcion = r.Descripcion
                            };   

                return query.ToList();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void AsociarPerfiles(int p_IdFiltro, List<string> p_Perfiles)
        {
            try
            {
                EliminarTodasLasAsociaciones(p_IdFiltro);
 
                foreach (string item in p_Perfiles)
                {
                    AsociarPerfil(p_IdFiltro, item);
                }                              
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void AsociarPerfil(int p_IdFiltro, string p_IdPerfil)
        {
            try
            {                
                adm_filtro_perfil PerfilAsociado = new adm_filtro_perfil
                {
                   flg_iCodigoFiltro  = p_IdFiltro,
                   flg_sCodigoGrupoUsuario = p_IdPerfil
                };

                Insertar(PerfilAsociado);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int Crear(FiltroPortafolio p_Filtro)
        {
            try
            {
                adm_filtro Filtro = new adm_filtro
                {
                    flp_sDescripcion = p_Filtro.Descripcion,
                    flp_sQuery = p_Filtro.Query
                };

                Insertar(Filtro);

                return Filtro.flp_iCodigo;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Eliminar(int p_IdFiltro)
        {
            try
            {
                EliminarTodasLasAsociaciones(p_IdFiltro);

                adm_filtro i_Temp = new adm_filtro
                {
                    flp_iCodigo = p_IdFiltro
                };

                Eliminar(i_Temp);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Actualizar(FiltroPortafolio p_Filtro)
        {
            try
            {
                adm_filtro Filtro = new adm_filtro                
                {
                    
                     flp_iCodigo = p_Filtro.Id,
                     flp_sDescripcion = p_Filtro.Descripcion,
                     flp_sQuery = p_Filtro.Query                                        
                };

                Modificar(Filtro);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void EliminarAsociacion(int p_IdFiltro, string p_IdPerfil)
        {
            try
            {

                var query = from PerfilesAsociados in Context.adm_filtro_perfil
                            where PerfilesAsociados.flg_iCodigoFiltro == p_IdFiltro &&
                                  PerfilesAsociados.flg_sCodigoGrupoUsuario == p_IdPerfil
                            select PerfilesAsociados;

                foreach (adm_filtro_perfil item in query)
                {
                    Context.DeleteObject(item);
                }

                Context.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void EliminarAsociaciones(int p_IdFiltro, List<string> p_Perfiles)
        {
            try
            {
                foreach (string item in p_Perfiles)
                {
                    EliminarAsociacion(p_IdFiltro, item);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void EliminarTodasLasAsociaciones(int p_IdFiltro)
        {
            try
            {
                var query = from PerfilesAsociados in Context.adm_filtro_perfil
                            where PerfilesAsociados.flg_iCodigoFiltro == p_IdFiltro
                            select PerfilesAsociados;

                foreach (adm_filtro_perfil item in query)
                {
                    Context.DeleteObject(item);
                }

                Context.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
        public List<Rol> BuscarPerfilesSinFiltro()
        {
            try
            {
                IRepositorioUsuario t_Usuarios = DatabaseAccess.UsuarioRepositorio;

                List<Rol> t_Roles = t_Usuarios.BuscarRoles();

                var query = (from filtro in Context.adm_filtro_perfil
                             select filtro.flg_sCodigoGrupoUsuario)
                            .Distinct().ToList();

                List<Rol> t_RolesSinPerfil = new List<Rol>();

                foreach (Rol item in t_Roles)
                {
                    if (!SeEncuentraRolEnFiltros(query, item))
                    {
                        t_RolesSinPerfil.Add(item);
                    }
                }                

                return t_RolesSinPerfil;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static bool SeEncuentraRolEnFiltros(List<string> query, Rol item)
        {
            return query.Exists(t => t == item.Id);
        }
    }
}
